home *** CD-ROM | disk | FTP | other *** search
/ NOVA - For the NeXT Workstation / NOVA - For the NeXT Workstation.iso / SourceCode / MiniExamples / AskMe / ClockView.m < prev    next >
Encoding:
Text File  |  1991-05-06  |  6.0 KB  |  211 lines

  1. /* ClockView.m, a simple clock view 
  2.  * Author: Ali T. Ozer, NeXT Developer Support Group
  3.  * Created: May 26, 1989 (for version 0.9)
  4.  * Modified: June 14 and Aug 14, 1989 (for version 1.0)
  5.  * Redesigned for 2.0 by Julie Zelenski, NeXT Developer Support Group
  6.  * Adapted by Mai Nguyen for this mini-example. Basically, only the digital
  7.  * view of the clock is being used.
  8.  *
  9.  * Subclass of view to implement a simple clock. This view is pretty generic 
  10.  * and can probably be added to any program. 
  11.  * You may freely copy, distribute and reuse the code in this example.  
  12.  * NeXT disclaims any warranty of any kind, expressed or implied, as to its 
  13.  * fitness for any particular use.
  14.  */
  15.  
  16. #import "ClockView.h"
  17. #import "Clock.h"    // PSwrap routines
  18. #import <appkit/Application.h>
  19. #import <appkit/Button.h>
  20. #import <appkit/Window.h>
  21. #import <appkit/Font.h>
  22. #import <objc/NXStringTable.h>
  23. #import <string.h>
  24. #import <sys/time.h>    
  25. #import <dpsclient/wraps.h>    
  26. #import <appkit/nextstd.h>
  27.  
  28. @implementation ClockView:View
  29.  
  30.         
  31. /* ShowTime() is the timed entry function called by the
  32.  * timed entry mechanism. It first writes the time out on the face 
  33.  * of the clock, and then reinstalls the timed entry if the clock is 
  34.  * not showing the seconds. If the seconds are being shown, no need to 
  35.  * reinstall the timed entry; a second skipped here and then won't matter. 
  36.  * If minutes are being shown, we want to make sure that the minute jumps 
  37.  * at the next top of the minute, regardless of how long it took to service 
  38.  * the timed entry.
  39.  */
  40. void ShowTime (teNum, now, clock) 
  41. DPSTimedEntry teNum;
  42. double now;
  43. id clock;
  44. {
  45.     [clock display];    
  46.     
  47. }
  48.  
  49.  
  50.  
  51.  
  52. - initFrame:(const NXRect *)frameRect
  53. /* initFrame for newly created view, initializes the various paramaters. 
  54.  * The constants above determine the lengths of the clock hands.
  55.  */
  56. {
  57.     [super initFrame:frameRect];
  58.     cacheWindow = [Window newContent:frameRect 
  59.                                style:NX_PLAINSTYLE
  60.                  backing:NX_RETAINED 
  61.               buttonMask:0 
  62.                    defer:NO];    
  63.     littleFont = [Font newFont:"Helvetica" size:12 style:0
  64.                 matrix:NX_IDENTITYMATRIX];
  65.     mediumFont = [Font newFont:"Times-Roman" size:14 style:0
  66.                 matrix:NX_IDENTITYMATRIX];
  67.     bigFont = [Font newFont:"Times-Roman" size:24 style:0
  68.                 matrix:NX_IDENTITYMATRIX];
  69.  
  70.     /* Set the default state (NO seconds, no date) */
  71.     
  72.     showSeconds = NO;
  73.     center.x = bounds.size.width/2.0;
  74.     center.y = bounds.size.height/2.0 + [mediumFont pointSize]/2.0;
  75.     radius = MIN(center.x,center.y-[mediumFont pointSize]);
  76.     needRedraw = YES;
  77.     
  78.     /* Start the time entry. YES indicates that this is the first time */
  79.     [self startTimedEntry:YES];
  80.     [self display];
  81.     return self;
  82. }
  83.  
  84.  
  85. - free
  86. /* Good idea to get rid of the timed entry while freeing... 
  87.  */
  88. {
  89.     [cacheWindow free];
  90.     [self stopTimedEntry];
  91.     return [super free];
  92. }
  93.  
  94.  
  95.  
  96.  
  97. /* PRIVATE METHODS */
  98.  
  99. - drawFace;
  100. /* drawFace draws the clock face image in the offscreen window.  This
  101.  * offscreen cache is composited on screen and then the hands, shadow,
  102.  * whatever is drawn on top of the face for the current time. Just
  103.  * erase the background before redrawing the digital time.
  104.  */
  105. {
  106.     
  107.     [[cacheWindow contentView] lockFocus];
  108.  
  109.     PSsetgray (NX_LTGRAY);
  110.     NXRectFill (&bounds);    // Erase background    
  111.     [[cacheWindow contentView] unlockFocus]; 
  112.     needRedraw = NO;
  113.     return self;
  114. }
  115.  
  116. - drawDigital:(struct tm *)time;
  117. /* drawDigital draws the time and date for the digital clock face
  118.  */
  119. {
  120.     int hour;
  121.     char timeString[10];
  122.    
  123.     
  124.     hour = fmod(time->tm_hour,12); /* get us off military time */
  125.     if (!hour) hour = 12;  /* if noon or midnight */
  126.     if (showSeconds)
  127.         sprintf(timeString,"%d:%.2d:%.2d",hour,
  128.                         time->tm_min,
  129.                         time->tm_sec);
  130.     else 
  131.         sprintf(timeString,"%d:%.2d", hour,time->tm_min);
  132.     [mediumFont set];
  133.     PSWcenterShow(center.x,center.y-8.0,timeString,NX_BLACK);
  134.     return self;
  135. }
  136.  
  137.  
  138.  
  139.  
  140. - drawSelf:(NXRect *)rects :(int)rectCount
  141. /* Draws face and hands of clock. If needRedraw is YES, a parameter has 
  142.  * changed and the face must be redrawn in the offscreen window. 
  143.  * Otherwise, the image in cacheWindow is copied into the bounds of the 
  144.  * view, and a routine is called to display the current date and time
  145.  */ 
  146. {    
  147.     struct tm *localTime;
  148.     struct timeval currentTime;
  149.  
  150.     if (needRedraw) [self drawFace];
  151.     PScomposite(0.0, 0.0, bounds.size.width, bounds.size.height,
  152.         [cacheWindow gState], bounds.origin.x, bounds.origin.y, 
  153.         NX_COPY);
  154.  
  155.     gettimeofday (¤tTime, NULL);
  156.     localTime = localtime (&(currentTime.tv_sec));
  157.     [self drawDigital:localTime];
  158.     return self;
  159. }
  160.  
  161.  
  162. - startTimedEntry:(BOOL)fireASAP
  163. /* startTimedEntry will install the timed entry. If fireASAP is YES, the
  164.  * timed entry is set to fire off as soon as possible (this would be the case
  165.  * at the start of the program, for instance). If fireASAP is NO, then the
  166.  * timed entry is set to fire off in one second (if seconds are being shown)
  167.  * or at the top of the next minute (in anytime between 0 and 60 seconds).
  168.  */
  169. {
  170.     double fireIn;
  171.  
  172.     if (fireASAP) fireIn = 0.0;          // Fire as soon as possible!
  173.     else if (showSeconds) fireIn = 1.0;      // Fire in a second (good enough)
  174.     else {
  175.         struct timeval currentTime;
  176.         gettimeofday (¤tTime, NULL);
  177.     fireIn = 60.0 - (currentTime.tv_sec % 60);  // Top of the minute
  178.     }
  179.     
  180.     teNum = DPSAddTimedEntry(fireIn, &ShowTime, self, NX_MODALRESPTHRESHOLD);
  181.     return self;
  182. }
  183.  
  184. - stopTimedEntry
  185. /* Removes the clock timed entry.
  186.  */
  187. {
  188.     if (teNum)
  189.          DPSRemoveTimedEntry (teNum);
  190.     teNum = (DPSTimedEntry)0;
  191.     return self;
  192. }
  193.  
  194.  
  195. - sizeTo:(NXCoord)w :(NXCoord)h
  196. /* Overriding sizeTo:: allows us to resize and fix up the clock whenever
  197.  * the size is changed.  Figure the radius of the clock (based on the size
  198.  * of the view) and then redraw
  199.  */
  200. {
  201.     [super sizeTo:w :h];
  202.     center.x = bounds.size.width/2.0;
  203.     center.y = bounds.size.height/2.0 + [mediumFont pointSize]/2.0;
  204.     radius = MIN(center.x, center.y-[mediumFont pointSize]);
  205.     needRedraw = YES;
  206.     return self;
  207. }
  208.  
  209.  
  210.  
  211. @end